package com.hnjfzn.message.sms.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hnjfzn.common.core.constant.Constants;
import com.hnjfzn.common.core.context.SecurityContextHolder;
import com.hnjfzn.common.core.exception.sms.SmsException;
import com.hnjfzn.common.core.utils.StringUtils;
import com.hnjfzn.common.redis.service.RedisService;
import com.hnjfzn.message.sms.domain.SmsLog;
import com.hnjfzn.message.sms.domain.bo.SmsParams;
import com.hnjfzn.message.sms.domain.bo.UtilResult;
import com.hnjfzn.message.sms.domain.enums.SmsPlatformType;
import com.hnjfzn.message.sms.domain.enums.SmsType;
import com.hnjfzn.message.sms.mapper.SmsLogMapper;
import com.hnjfzn.message.sms.service.ISmsService;
import com.hnjfzn.message.sms.service.IThirdService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import static com.hnjfzn.common.core.constant.CacheConstants.MSG_SMS_CODE_KEY;
import static com.hnjfzn.common.core.constant.CacheConstants.MSG_SMS_LOCK_KEY;
import static com.hnjfzn.common.core.constant.SmsConstants.SMS_PLATFORM_KEY;
import static com.hnjfzn.common.core.constant.SmsConstants.SMS_SIGN_KEY;

@Service
public class SmsServiceImpl extends ServiceImpl<SmsLogMapper, SmsLog> implements ISmsService {

    @Autowired
    private RedisService redisService;

    @Resource(type = ThirdAliServiceImpl.class)
    private IThirdService aliService;

    @Resource(type = ThirdHuLianServiceImpl.class)
    private IThirdService hlService;

    @Override
    public Long sendCaptcha(String phone) throws SmsException {
        String sign = SecurityContextHolder.get(SMS_SIGN_KEY);
        String codeKey = String.format(MSG_SMS_CODE_KEY, phone);
        String lockKey = String.format(MSG_SMS_LOCK_KEY, phone);
        try {
            // 锁
            if (redisService.hasKey(lockKey)){
                throw new SmsException("请勿重复点击", SmsException.Code.REPEAT_CLICK);
            }
            redisService.setCacheObject(lockKey, true, 30L, TimeUnit.SECONDS);

            // 检测手机号是否发送过验证码
            String code = redisService.getCacheObject(codeKey);
            if (StringUtils.isNotEmpty(code)) {
                return Long.valueOf(code.split("&")[0]);
            }

            // 随机生成验证码，有效时间1分钟
            code = generateSixDigitCode();

            // 数据
            SmsParams smsParams = new SmsParams();
            smsParams.setPhone(phone);
            smsParams.setContent("您的验证码是" + code + "。");
            smsParams.setData(Collections.singletonMap("code", code));
            smsParams.setSign(sign);

            // 如非本人操作，请忽略本短信签名
            UtilResult ur = send(SmsType.CAPTCHA, smsParams);
            if (ur.isSuccess()) {
                String smsId = ur.getResult();
                if (StringUtils.isEmpty(smsId)) {
                    throw new SmsException("发送异常", SmsException.Code.SMS_SEND_ERROR);
                }
                redisService.setCacheObject(codeKey, smsId.concat("&").concat(code), Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
                return Long.valueOf(smsId);
            }
        } finally {
            redisService.deleteObject(lockKey);
        }
        throw new SmsException("获取验证码异常，请联系管理员", SmsException.Code.GET_SMS_ERROR);
    }

    private UtilResult send(SmsType type, SmsParams params) {
        // 发送短信平台
        SmsPlatformType platformType = SecurityContextHolder.get(SMS_PLATFORM_KEY, SmsPlatformType.class);
        // 访问
        UtilResult ur = UtilResult.builder().success(false).msg("发送短信失败，请联系管理员").build();
        // 业务code
        switch (platformType) {
            case ALI:
                switch (type) {
                    case CAPTCHA:
                        params.setCode("SMS_305521368");
                        break;
                }
                ur = aliService.send(params);
                break;
            case HL365:
                ur = hlService.send(params);
                break;
        }

        // 保存记录
        SmsLog thirdAliSms = new SmsLog();
        thirdAliSms.setSendTime(new Date());
        thirdAliSms.setRecipient(params.getPhone());
        thirdAliSms.setContent(params.message());
        thirdAliSms.setResult(ur.getResult());
        thirdAliSms.setSmsType(type.getCode());
        thirdAliSms.setSmsPlatform(platformType.getCode());
        save(thirdAliSms);

        // 结果处理
        if (ur.isSuccess()) {
            ur.setResult(thirdAliSms.getSmsId().toString());
        }
        return ur;
    }

    private String generateSixDigitCode() {
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();
    }
}
